package pl.edu.pw.elka.jtrzasko.proz.warcaby.controller;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import pl.edu.pw.elka.jtrzasko.proz.warcaby.actions.server.ServerActionActivePlayer;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.actions.server.ServerActionBoard;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.actions.server.ServerActionGameDraw;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.actions.server.ServerActionGameOver;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.actions.server.ServerActionPlayerColor;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.MessageFactory;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.client.ClientMessage;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.client.ClientMessageStart;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessage;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessageActivePlayer;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessageBoard;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessageGameDraw;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessageGameOver;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessagePlayerColor;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.view.ClientView;

/**
 * Klasa jest odpowidzialna za wysylanie informacji do serwera gry
 */
public class ClientController implements Runnable
{
	/**
	 * Widok powiazany z klientem
	 */
	private ClientView clientView;
	/**
	 * Port na ktorym laczymy sie z serwerem
	 */
	private int port;
	/**
	 * Strumien do zapisu inforamcji odbieranych od serwera
	 */
	private ObjectInputStream in;
	/**
	 *  Strumien do zapisu inforamcji wysylanych do serwera
	 */
	private ObjectOutputStream out;

	/**
	 * Gniazdo dla danego Klienta
	 */
	private Socket socket;
	/**
	 * Nazwa serwera z ktorym sie laczymy
	 */
	private String serverName;

	/**
	 * Tworzy nawa instancje klienta
	 * @param clientView Widok powiazany z tym klientem
	 * @param serverName Nazwa serwra z ktrym sie laczymy
	 * @param port Port na ktorym laczymy sie do serwera
	 */
	public ClientController(ClientView clientView, String serverName, int port)
	{
		this.clientView = clientView;
		this.serverName = serverName;
		this.port = port;		
		
		MessageFactory.registerMessage(ServerMessageActivePlayer.class.getSimpleName(), new ServerActionActivePlayer());
		MessageFactory.registerMessage(ServerMessageBoard.class.getSimpleName(), new ServerActionBoard());
		MessageFactory.registerMessage(ServerMessageGameDraw.class.getSimpleName(), new ServerActionGameDraw());
		MessageFactory.registerMessage(ServerMessageGameOver.class.getSimpleName(), new ServerActionGameOver());
		MessageFactory.registerMessage(ServerMessagePlayerColor.class.getSimpleName(), new ServerActionPlayerColor());
	}

	public void run()
	{
		try
		{
			socket = new Socket(serverName, port);
			in = new ObjectInputStream(socket.getInputStream());
			out = new ObjectOutputStream(socket.getOutputStream());
			out.flush();
			out.reset();
			sendMessage(new ClientMessageStart());
			while (true)
			{
				ServerMessage message = (ServerMessage) in.readObject();
				MessageFactory.runServerAction(message, clientView);
			}
		} catch (Exception e)
		{
			System.out.println("Client ended");
		} finally
		{
			clientView.getButtonDisconnect().doClick();
		}
	}

	/**
	 * Wysyla widomosc do serwera
	 * @param m Widomosc
	 */
	public void sendMessage(ClientMessage m)
	{
		try
		{
			out.writeObject(m);
			out.flush();
			out.reset();
		} catch (Exception e)
		{
			System.out.println("Client couldn't send Message");
		}
	}

	/**
	 * Przerwanie polaczenia z klientem
	 */
	public void disconnet()
	{
		try
		{
			socket.close();
		} catch (Exception e)
		{
			System.out.println("Couldn't close client socket");
		}

	}

}
